home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Tools / Development / libogg / libvorbis-1.0rc3 / lib / envelope.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-10-27  |  7.9 KB  |  287 lines

  1. /********************************************************************
  2.  *                                                                  *
  3.  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
  4.  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
  5.  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  6.  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  7.  *                                                                  *
  8.  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001             *
  9.  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
  10.  *                                                                  *
  11.  ********************************************************************
  12.  
  13.  function: PCM data envelope analysis and manipulation
  14.  last mod: $Id: envelope.c,v 1.41 2001/12/20 01:00:26 segher Exp $
  15.  
  16.  Preecho calculation.
  17.  
  18.  ********************************************************************/
  19.  
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <stdio.h>
  23. #include <math.h>
  24. #include <ogg/ogg.h>
  25. #include "vorbis/codec.h"
  26. #include "codec_internal.h"
  27.  
  28. #include "os.h"
  29. #include "scales.h"
  30. #include "envelope.h"
  31. #include "misc.h"
  32. #include "iir.c" /* Yes, ugly, but needed for inlining */
  33.  
  34. /* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher */
  35.  
  36. static int   cheb_highpass_stages=6;
  37. static float cheb_highpass_B[]={1.f,-6.f,15.f,-20.f,15.f,-6.f,1.f};
  38.  
  39. static int   cheb_bandpass_stages=6;
  40. static float cheb_bandpass_B[]={-1.f,0.f,3.f,0.f,-3.f,0.f,1.f};
  41.  
  42.  
  43. /* 10kHz Chebyshev highpass */
  44. static float cheb_highpass10k_gain= 54.34519586f;
  45. static float cheb_highpass10k_A[]={
  46.   -0.2064797169f,
  47.   -0.5609713214f,
  48.   -1.1352465327f,
  49.   -1.4495555418f,
  50.   -1.7938140760f,
  51.   -0.9473564683f};
  52.  
  53. /* 6kHz-10kHz Chebyshev bandpass */
  54. static float cheb_bandpass6k_gain=113.4643935f;
  55. static float cheb_bandpass6k_A[]={
  56.   -0.5712621337f,
  57.   1.5626130710f,
  58.   -3.3348854983f,
  59.   4.0471340821f,
  60.   -4.0051680331f,
  61.   2.2786325610f};
  62.  
  63. /* 3kHz-6kHz Chebyshev bandpass */
  64. static float cheb_bandpass3k_gain= 248.8359377f;
  65. static float cheb_bandpass3k_A[]={
  66.   -0.6564230022f,
  67.   3.3747911257f,
  68.   -8.0098635981f,
  69.   11.0040876874f,
  70.   -9.2250963484f,
  71.   4.4760355389f};
  72.  
  73. /* 1.5kHz-3kHz Chebyshev bandpass */
  74. static float cheb_bandpass1k_gain= 1798.537183f;
  75. static float cheb_bandpass1k_A[]={
  76.   -0.8097527363f,
  77.   4.7725742682f,
  78.   -11.9800219408f,
  79.   16.3770336223f,
  80.   -12.8553129536f,
  81.   5.4948074309f};
  82.  
  83. void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){
  84.   codec_setup_info *ci=vi->codec_setup;
  85.   vorbis_info_psy_global *gi=&ci->psy_g_param;
  86.   int ch=vi->channels;
  87.   int i;
  88.   e->winlength=ci->blocksizes[0]/2; /* not random */
  89.   e->minenergy=fromdB(gi->preecho_minenergy);
  90.   e->iir=_ogg_calloc(ch*4,sizeof(*e->iir));
  91.   e->filtered=_ogg_calloc(ch*4,sizeof(*e->filtered));
  92.   e->ch=ch;
  93.   e->storage=128;
  94.   for(i=0;i<ch*4;i+=4){
  95.  
  96.     IIR_init(e->iir+i,cheb_highpass_stages,cheb_highpass10k_gain,
  97.          cheb_highpass10k_A,cheb_highpass_B);
  98.     IIR_init(e->iir+i+1,cheb_bandpass_stages,cheb_bandpass6k_gain,
  99.          cheb_bandpass6k_A,cheb_bandpass_B);
  100.     IIR_init(e->iir+i+2,cheb_bandpass_stages,cheb_bandpass3k_gain,
  101.          cheb_bandpass3k_A,cheb_bandpass_B);
  102.     IIR_init(e->iir+i+3,cheb_bandpass_stages,cheb_bandpass1k_gain,
  103.          cheb_bandpass1k_A,cheb_bandpass_B);
  104.  
  105.     e->filtered[i]=_ogg_calloc(e->storage,sizeof(*e->filtered[i]));
  106.     e->filtered[i+1]=_ogg_calloc(e->storage,sizeof(*e->filtered[i+1]));
  107.     e->filtered[i+2]=_ogg_calloc(e->storage,sizeof(*e->filtered[i+2]));
  108.     e->filtered[i+3]=_ogg_calloc(e->storage,sizeof(*e->filtered[i+3]));
  109.   }
  110.  
  111. }
  112.  
  113. void _ve_envelope_clear(envelope_lookup *e){
  114.   int i;
  115.   for(i=0;i<e->ch*4;i++){
  116.     IIR_clear((e->iir+i));
  117.     _ogg_free(e->filtered[i]);
  118.   }
  119.   _ogg_free(e->filtered);
  120.   _ogg_free(e->iir);
  121.   memset(e,0,sizeof(*e));
  122. }
  123.  
  124. /* straight threshhold based until we find something that works better
  125.    and isn't patented */
  126. static float _ve_deltai(envelope_lookup *ve,float *pre,float *post){
  127.   long n=ve->winlength;
  128.  
  129.   long i;
  130.  
  131.   /* we want to have a 'minimum bar' for energy, else we're just
  132.      basing blocks on quantization noise that outweighs the signal
  133.      itself (for low power signals) */
  134.  
  135.   float minV=ve->minenergy;
  136.   float A=minV*minV*n;
  137.   float B=A;
  138.  
  139.   for(i=0;i<n;i++){
  140.     A+=pre[i]*pre[i];
  141.     B+=post[i]*post[i];
  142.   }
  143.  
  144.   A=todB(&A);
  145.   B=todB(&B);
  146.  
  147.   return(B-A);
  148. }
  149.  
  150. long _ve_envelope_search(vorbis_dsp_state *v){
  151.   vorbis_info *vi=v->vi;
  152.   codec_setup_info *ci=vi->codec_setup;
  153.   vorbis_info_psy_global *gi=&ci->psy_g_param;
  154.   envelope_lookup *ve=((backend_lookup_state *)(v->backend_state))->ve;
  155.   long i,j,k;
  156.  
  157.   /* make sure we have enough storage to match the PCM */
  158.   if(v->pcm_storage>ve->storage){
  159.     ve->storage=v->pcm_storage;
  160.     for(i=0;i<ve->ch*4;i++)
  161.       ve->filtered[i]=_ogg_realloc(ve->filtered[i],ve->storage*sizeof(*ve->filtered[i]));
  162.   }
  163.  
  164.   /* catch up the highpass to match the pcm */
  165.   for(i=0;i<ve->ch;i++){
  166.     float *pcm=v->pcm[i];
  167.     float *filtered0=ve->filtered[i*4];
  168.     float *filtered1=ve->filtered[i*4+1];
  169.     float *filtered2=ve->filtered[i*4+2];
  170.     float *filtered3=ve->filtered[i*4+3];
  171.     IIR_state *iir0=ve->iir+i*4;
  172.     IIR_state *iir1=ve->iir+i*4+1;
  173.     IIR_state *iir2=ve->iir+i*4+2;
  174.     IIR_state *iir3=ve->iir+i*4+3;
  175.     int flag=1;
  176.     for(j=ve->current;j<v->pcm_current;j++){
  177.       filtered0[j]=IIR_filter(iir0,pcm[j]);
  178.       filtered1[j]=IIR_filter_Band(iir1,pcm[j]);
  179.       filtered2[j]=IIR_filter_Band(iir2,pcm[j]);
  180.       filtered3[j]=IIR_filter_Band(iir3,pcm[j]);
  181.       if(pcm[j])flag=0;
  182.     }
  183.     if(flag && ve->current+64<v->pcm_current){
  184.       IIR_reset(iir0);
  185.       IIR_reset(iir1);
  186.       IIR_reset(iir2);
  187.       IIR_reset(iir3);
  188.     }
  189.  
  190.   }
  191.  
  192.   ve->current=v->pcm_current;
  193.  
  194.   {
  195.     int flag=-1;
  196.     long centerW=v->centerW;
  197.     long beginW=centerW-ci->blocksizes[v->W]/4;
  198.     /*long endW=centerW+ci->blocksizes[v->W]/4+ci->blocksizes[0]/4;*/
  199.     long testW=centerW+ci->blocksizes[v->W]/4+ci->blocksizes[1]/2+ci->blocksizes[0]/4;
  200.     if(v->W)
  201.       beginW-=ci->blocksizes[v->lW]/4;
  202.     else
  203.       beginW-=ci->blocksizes[0]/4;
  204.  
  205.     if(ve->mark>=centerW && ve->mark<testW)return(0);
  206.     if(ve->mark>=testW)return(1);
  207.  
  208.     if(v->W)
  209.       j=ve->cursor;
  210.     else
  211.       j=centerW-ci->blocksizes[0]/4;
  212.     
  213.     while(j+ve->winlength*3/2<=v->pcm_current){
  214.       if(j>=testW)return(1);
  215.       ve->cursor=j;
  216.  
  217.       for(i=0;i<ve->ch;i++){
  218.     for(k=0;k<4;k++){
  219.       float *filtered=ve->filtered[i*4+k]+j;
  220.       float *filtered2=ve->filtered[i*4+k]+j+ve->winlength/2;
  221.       float m=_ve_deltai(ve,filtered-ve->winlength,filtered);
  222.       float mm=_ve_deltai(ve,filtered2-ve->winlength,filtered2);
  223.       
  224.       if(m>gi->preecho_thresh[k] || m<gi->postecho_thresh[k]){
  225.         if(j<=centerW){
  226.           ve->prevmark=ve->mark=j;
  227.         }else{
  228.           /* if a quarter-short-block advance is an even stronger
  229.          reading, set *that* as the impulse point. */
  230.           if((m>0. && mm>m) || (m<0. && mm<m))
  231.         flag=j+ve->winlength/2;
  232.           else
  233.         if(flag<0)flag=j;
  234.         }
  235.       }
  236.     }
  237.       }
  238.       
  239.       if(flag>=0){
  240.      ve->prevmark=ve->mark;
  241.     ve->mark=flag;
  242.     if(flag>=testW)return(1);
  243.     return(0);
  244.       }
  245.       
  246.       j+=ve->winlength/2;
  247.     }
  248.   }
  249.  
  250.   return(-1);
  251. }
  252.  
  253. int _ve_envelope_mark(vorbis_dsp_state *v){
  254.   envelope_lookup *ve=((backend_lookup_state *)(v->backend_state))->ve;
  255.   vorbis_info *vi=v->vi;
  256.   codec_setup_info *ci=vi->codec_setup;
  257.   long centerW=v->centerW;
  258.   long beginW=centerW-ci->blocksizes[v->W]/4;
  259.   long endW=centerW+ci->blocksizes[v->W]/4;
  260.   if(v->W){
  261.     beginW-=ci->blocksizes[v->lW]/4;
  262.     endW+=ci->blocksizes[v->nW]/4;
  263.   }else{
  264.     beginW-=ci->blocksizes[0]/4;
  265.     endW+=ci->blocksizes[0]/4;
  266.   }
  267.  
  268.   if(ve->prevmark>=beginW && ve->prevmark<endW)return(1);
  269.   if(ve->mark>=beginW && ve->mark<endW)return(1);
  270.   return(0);
  271. }
  272.  
  273. void _ve_envelope_shift(envelope_lookup *e,long shift){
  274.   int i;
  275.   for(i=0;i<e->ch*4;i++)
  276.     memmove(e->filtered[i],e->filtered[i]+shift,(e->current-shift)*
  277.         sizeof(*e->filtered[i]));
  278.   e->current-=shift;
  279.   if(e->prevmark>=0)
  280.     e->prevmark-=shift;
  281.   if(e->mark>=0)
  282.     e->mark-=shift;
  283.   e->cursor-=shift;
  284. }
  285.  
  286.  
  287.